<template>
  <el-dialog
    :title="`Base64编码解码`"
    v-model="drawerVisible"
    :draggable="true"
    :overflow="true"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    top="30px"
    width="70%"
    :destroy-on-close="true"
  >
    <el-form ref="ruleFormRef" style="overflow-y: auto" label-width="120px" label-position="left">
      <div class="base64-form">
        <!-- 输入区域 -->
        <div class="input-section">
          <h3 class="section-title">
            <el-icon><EditPen /></el-icon>
            输入内容
          </h3>
          <div class="input-container">
            <el-input
              type="textarea"
              :rows="8"
              placeholder="请输入要编码/解码的内容"
              v-model="srcStr"
              :maxlength="maxLength"
              show-word-limit
              @input="onInputChange"
            />
            <div class="input-info">
              <span class="char-count">字符数: {{ srcStr.length }}</span>
              <span class="byte-count">字节数: {{ getByteLength(srcStr) }}</span>
            </div>
          </div>
        </div>

        <!-- 操作按钮区域 -->
        <div class="operation-section">
          <div class="btn-group">
            <el-button type="primary" @click="onEncode" :loading="processing" :disabled="!srcStr">
              <el-icon><ArrowDown /></el-icon>
              编码 (Base64)
            </el-button>
            <el-button type="success" @click="onDecode" :loading="processing" :disabled="!srcStr">
              <el-icon><ArrowDown /></el-icon>
              解码 (文本)
            </el-button>
            <el-button @click="onSwap" :disabled="!srcStr && !toStr">
              <el-icon><Switch /></el-icon>
              交换内容
            </el-button>
            <el-button @click="onClear">
              <el-icon><Delete /></el-icon>
              清空
            </el-button>
          </div>
        </div>

        <!-- 输出区域 -->
        <div class="output-section">
          <h3 class="section-title">
            <el-icon><View /></el-icon>
            转换结果
            <span v-if="toStr" class="result-info">({{ toStr.length }}字符)</span>
          </h3>
          <div class="output-container">
            <el-input type="textarea" :rows="8" placeholder="转换结果将在这里显示" v-model="toStr" readonly />
            <div class="output-actions" v-if="toStr">
              <el-button size="small" @click="copyResult">
                <el-icon><CopyDocument /></el-icon>
                复制结果
              </el-button>
              <el-button size="small" @click="downloadResult">
                <el-icon><Download /></el-icon>
                下载结果
              </el-button>
            </div>
          </div>
        </div>

        <!-- 功能说明 -->
        <div class="info-section">
          <el-alert title="使用说明" type="info" :closable="false" show-icon>
            <template #default>
              <ul class="info-list">
                <li>Base64编码：将任意文本转换为Base64格式，常用于数据传输</li>
                <li>Base64解码：将Base64格式还原为原始文本内容</li>
                <li>支持中文、特殊字符和换行符的正确处理</li>
                <li>自动检测输入格式，智能提示操作建议</li>
              </ul>
            </template>
          </el-alert>
        </div>
      </div>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="drawerVisible = false">关闭</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts" name="Base64Converter">
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { EditPen, View, ArrowDown, Switch, Delete, CopyDocument, Download } from "@element-plus/icons-vue";

interface DrawerProps {}

const drawerVisible = ref(false);
const drawerProps = ref<DrawerProps>({});
const srcStr = ref("");
const toStr = ref("");
const processing = ref(false);
const maxLength = 50000; // 最大字符限制

// 计算字节长度
const getByteLength = (str: string): number => {
  return new Blob([str]).size;
};

// 检测是否为Base64格式
const isBase64 = (str: string): boolean => {
  if (!str) return false;
  try {
    return btoa(atob(str)) === str;
  } catch (err) {
    return false;
  }
};

// 输入变化处理
const onInputChange = () => {
  if (!srcStr.value) {
    toStr.value = "";
    return;
  }

  // 自动检测并提示
  if (isBase64(srcStr.value)) {
    ElMessage.info("检测到Base64格式，建议使用解码功能");
  }
};

// Base64编码
const onEncode = async () => {
  if (!srcStr.value.trim()) {
    ElMessage.warning("请输入要编码的内容");
    return;
  }

  processing.value = true;

  try {
    // 使用更安全的编码方式
    const encoded = btoa(unescape(encodeURIComponent(srcStr.value)));
    toStr.value = encoded;
    ElMessage.success("Base64编码成功");
  } catch (error) {
    console.error("编码失败:", error);
    ElMessage.error("编码失败，请检查输入内容");
  } finally {
    processing.value = false;
  }
};

// Base64解码
const onDecode = async () => {
  if (!srcStr.value.trim()) {
    ElMessage.warning("请输入要解码的Base64内容");
    return;
  }

  processing.value = true;

  try {
    // 验证Base64格式
    if (!isBase64(srcStr.value.trim())) {
      throw new Error("无效的Base64格式");
    }

    const decoded = decodeURIComponent(escape(atob(srcStr.value.trim())));
    toStr.value = decoded;
    ElMessage.success("Base64解码成功");
  } catch (error) {
    console.error("解码失败:", error);
    ElMessage.error("解码失败，请检查Base64格式是否正确");
  } finally {
    processing.value = false;
  }
};

// 交换内容
const onSwap = () => {
  const temp = srcStr.value;
  srcStr.value = toStr.value;
  toStr.value = temp;
  ElMessage.success("内容已交换");
};

// 清空内容
const onClear = () => {
  srcStr.value = "";
  toStr.value = "";
  ElMessage.success("内容已清空");
};

// 复制结果
const copyResult = async () => {
  if (!toStr.value) {
    ElMessage.warning("没有可复制的内容");
    return;
  }

  try {
    await navigator.clipboard.writeText(toStr.value);
    ElMessage.success("复制成功");
  } catch (error) {
    // 降级方案
    const textArea = document.createElement("textarea");
    textArea.value = toStr.value;
    document.body.appendChild(textArea);
    textArea.select();
    document.execCommand("copy");
    document.body.removeChild(textArea);
    ElMessage.success("复制成功");
  }
};

// 下载结果
const downloadResult = () => {
  if (!toStr.value) {
    ElMessage.warning("没有可下载的内容");
    return;
  }

  const blob = new Blob([toStr.value], { type: "text/plain;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = `base64_result_${Date.now()}.txt`;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url);
  ElMessage.success("下载成功");
};

// 接收父组件传过来的参数
const acceptParams = async (params: DrawerProps) => {
  drawerProps.value = params;
  drawerVisible.value = true;
  // 重置表单
  srcStr.value = "";
  toStr.value = "";
};

defineExpose({
  acceptParams
});
</script>

<style lang="scss" scoped>
.base64-form {
  display: flex;
  flex-direction: column;
  gap: 24px;
  .input-section,
  .output-section {
    .section-title {
      display: flex;
      gap: 8px;
      align-items: center;
      margin: 0 0 12px;
      font-size: 16px;
      font-weight: 600;
      color: var(--el-text-color-primary);
      .el-icon {
        color: var(--el-color-primary);
      }
      .result-info {
        font-size: 14px;
        font-weight: normal;
        color: var(--el-text-color-regular);
      }
    }
    .input-container,
    .output-container {
      position: relative;
    }
    .input-info {
      display: flex;
      gap: 16px;
      margin-top: 8px;
      font-size: 12px;
      color: var(--el-text-color-secondary);
      .char-count,
      .byte-count {
        padding: 2px 8px;
        background: var(--el-fill-color-light);
        border-radius: 4px;
      }
    }
    .output-actions {
      display: flex;
      gap: 8px;
      margin-top: 8px;
    }
  }
  .operation-section {
    display: flex;
    justify-content: center;
    padding: 16px 0;
    background: var(--el-bg-color-page);
    border: 1px solid var(--el-border-color-lighter);
    border-radius: 8px;
    .btn-group {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      justify-content: center;
    }
  }
  .info-section {
    .info-list {
      padding-left: 20px;
      margin: 8px 0 0;
      li {
        margin-bottom: 4px;
        font-size: 13px;
        line-height: 1.5;
      }
    }
  }
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
}

// 响应式设计
@media (width <= 768px) {
  .base64-form {
    gap: 16px;
    .operation-section {
      .btn-group {
        gap: 8px;
        .el-button {
          flex: 1;
          min-width: 0;
        }
      }
    }
  }
}
</style>
